package com.dkd.manage.task.allocator;

import com.dkd.manage.domain.Emp;
import com.dkd.manage.domain.Node;
import com.dkd.manage.domain.VendingMachine;
import com.dkd.manage.task.allocator.algorithm.*;
import com.dkd.manage.task.allocator.model.*;
import com.dkd.manage.task.allocator.service.PerformanceCalculator;
import com.dkd.manage.task.allocator.service.DistanceCalculator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class AdvancedEmployeeAllocator {

    @Autowired
    private PerformanceCalculator performanceCalculator;

    @Autowired
    private DistanceCalculator distanceCalculator;

    @Autowired
    private com.dkd.manage.service.IVendingMachineService vendingMachineService;

    // 缓存和监控
    private final Map<Long, EmployeePerformance> performanceCache = new ConcurrentHashMap<>();
    private final Map<Long, Long> cacheExpiry = new ConcurrentHashMap<>();
    private final PerformanceMonitor performanceMonitor = new PerformanceMonitor();
    private final Map<Long, EmployeeAllocationHistory> allocationHistory = new ConcurrentHashMap<>();

    private static final long CACHE_DURATION = 30 * 60 * 1000; // 30分钟缓存

    /**
     * 高级员工选择主入口
     */
    public Long selectOptimalEmployee(String innerCode, List<Emp> candidates, String taskType) {
        log.info("开始高级员工选择，设备: {}, 候选人数: {}, 任务类型: {}", innerCode, candidates.size(), taskType);

        if (candidates.isEmpty()) {
            log.warn("候选员工列表为空");
            return null;
        }

        if (candidates.size() == 1) {
            Long singleId = candidates.get(0).getId();
            log.info("只有一个候选员工，直接选择: {}", singleId);
            return singleId;
        }

        try {
            // 阶段1: 预筛选
            List<Emp> filteredCandidates = preFilterCandidates(candidates, taskType);
            if (filteredCandidates.isEmpty()) {
                log.warn("预筛选后无合适候选人，使用随机选择");
                return fallbackRandomSelection(candidates);
            }

            // 阶段2: 多算法并行计算
            Map<Long, AlgorithmScores> algorithmScores = executeParallelAlgorithms(innerCode, filteredCandidates, taskType);

            // 阶段3: 自适应权重融合
            Map<Long, Double> finalScores = adaptiveScoreFusion(algorithmScores, taskType);

            // 阶段4: 多策略选择
            Long selectedEmpId = executeSelectionStrategy(finalScores, filteredCandidates);

            // 阶段5: 记录分配历史
            recordAllocationHistory(selectedEmpId, innerCode, taskType, finalScores);

            log.info("高级员工选择完成，设备: {}, 选择员工: {}", innerCode, selectedEmpId);
            return selectedEmpId;

        } catch (Exception e) {
            log.error("高级员工选择异常: {}", e.getMessage(), e);
            return adaptiveFallback(candidates, taskType);
        }
    }

    /**
     * 预筛选候选人
     */
    private List<Emp> preFilterCandidates(List<Emp> candidates, String taskType) {
        return candidates.stream()
                .filter(emp -> isEmployeeAvailable(emp))
                .filter(emp -> meetsSkillRequirements(emp, taskType))
                .filter(emp -> withinWorkloadLimit(emp))
                .collect(Collectors.toList());
    }

    private boolean isEmployeeAvailable(Emp emp) {
        return emp.getStatus() == 1; // 状态为1表示启用
    }

    private boolean meetsSkillRequirements(Emp emp, String taskType) {
        // 直接从Emp对象获取技能等级，而不是从EmployeePerformance
        Integer empSkillLevel = emp.getSkillLevel();
        if (empSkillLevel == null) {
            empSkillLevel = 1; // 默认技能等级
        }

        // 如果需要，也可以从绩效数据中获取补充信息
        EmployeePerformance perf = getCachedPerformance(emp.getId());

        int requiredLevel = getRequiredSkillLevel(taskType);

        // 检查技能等级是否满足要求
        boolean skillMet = empSkillLevel >= requiredLevel;

        // 如果技能等级刚好满足最低要求，但绩效较差，可能需要进一步考虑
        if (skillMet && empSkillLevel.equals(requiredLevel)) {
            // 如果绩效得分低于6分，认为技能可能不足
            if (perf.getPerformanceScore() < 6.0) {
                log.debug("员工{}技能等级满足但绩效较差，需要谨慎考虑", emp.getId());
                // 这里可以添加更复杂的逻辑
            }
        }

        log.debug("员工{}技能检查: 等级{} vs 要求{}, 结果: {}",
                emp.getId(), empSkillLevel, requiredLevel, skillMet);

        return skillMet;
    }

    private boolean withinWorkloadLimit(Emp emp) {
        EmployeePerformance perf = getCachedPerformance(emp.getId());
        int maxTasks = emp.getMaxDailyTasks() != null ? emp.getMaxDailyTasks() : 8;
        return perf.getTodayTasks() < maxTasks && perf.getCurrentWorkload() < 5;
    }

    private int getRequiredSkillLevel(String taskType) {
        switch (taskType) {
            case "COMPLEX":
                return 3;
            case "URGENT":
                return 2;
            default:
                return 1;
        }
    }

    /**
     * 并行执行多种算法
     */
    private Map<Long, AlgorithmScores> executeParallelAlgorithms(String innerCode, List<Emp> candidates, String taskType) {
        Map<Long, AlgorithmScores> allScores = new ConcurrentHashMap<>();

        ExecutorService executor = Executors.newFixedThreadPool(6);
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        // 遗传算法
        futures.add(CompletableFuture.runAsync(() -> {
            GeneticAlgorithm ga = new GeneticAlgorithm(20, 10, 0.8, 0.1);
            Map<Long, Double> scores = ga.optimize(candidates, emp -> evaluateFitness(emp.getId(), innerCode, taskType));
            mergeScores(allScores, scores, "genetic");
        }, executor));

        // 粒子群优化
        futures.add(CompletableFuture.runAsync(() -> {
            ParticleSwarmOptimization pso = new ParticleSwarmOptimization(15, 20);
            Map<Long, Double> scores = pso.optimize(candidates, emp -> evaluateFitness(emp.getId(), innerCode, taskType));
            mergeScores(allScores, scores, "pso");
        }, executor));

        // 神经网络
        futures.add(CompletableFuture.runAsync(() -> {
            NeuralNetworkPredictor nn = NeuralNetworkPredictor.getInstance();
            Map<Long, Double> scores = new HashMap<>();
            for (Emp emp : candidates) {
                double[] features = createFeatureVector(emp, innerCode, taskType);
                double score = nn.predict(features);
                scores.put(emp.getId(), score);
            }
            mergeScores(allScores, scores, "neural");
        }, executor));

        // 模糊逻辑
        futures.add(CompletableFuture.runAsync(() -> {
            FuzzyLogicEvaluator fuzzy = new FuzzyLogicEvaluator();
            Map<Long, Double> scores = new HashMap<>();
            for (Emp emp : candidates) {
                EmployeePerformance perf = getCachedPerformance(emp.getId());
                VendingMachine machine = vendingMachineService.selectVendingMachineByInnerCode(innerCode);
                double workload = perf.getCurrentWorkload() / 10.0;
                double skillMatch = performanceCalculator.calculateSkillMatch(emp.getId(), machine);
                double distance = distanceCalculator.calculateDistanceLevel(
                        distanceCalculator.calculateDistance(emp, machine));
                double performance = perf.getPerformanceScore() / 10.0;

                double score = fuzzy.evaluate(workload, skillMatch, distance, performance);
                scores.put(emp.getId(), score);
            }
            mergeScores(allScores, scores, "fuzzy");
        }, executor));

        // 蚁群算法
        futures.add(CompletableFuture.runAsync(() -> {
            AntColonyOptimization aco = new AntColonyOptimization(10, 15, 1.0, 2.0, 0.5);
            Map<Long, Double> scores = aco.optimize(candidates, emp -> evaluateFitness(emp.getId(), innerCode, taskType));
            mergeScores(allScores, scores, "ant");
        }, executor));

        // 等待所有算法完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        executor.shutdown();

        log.info("多算法并行计算完成，生成 {} 个评分结果", allScores.size());
        return allScores;
    }

    private void mergeScores(Map<Long, AlgorithmScores> allScores, Map<Long, Double> newScores, String algorithm) {
        for (Map.Entry<Long, Double> entry : newScores.entrySet()) {
            AlgorithmScores scores = allScores.computeIfAbsent(entry.getKey(), k -> new AlgorithmScores());

            switch (algorithm) {
                case "genetic":
                    scores.setGeneticAlgorithmScore(entry.getValue());
                    break;
                case "pso":
                    scores.setParticleSwarmScore(entry.getValue());
                    break;
                case "neural":
                    scores.setNeuralNetworkScore(entry.getValue());
                    break;
                case "fuzzy":
                    scores.setFuzzyLogicScore(entry.getValue());
                    break;
                case "ant":
                    scores.setAntColonyScore(entry.getValue());
                    break;
            }
        }
    }

    /**
     * 评估适应度函数
     */
    private double evaluateFitness(Long empId, String innerCode, String taskType) {
        EmployeePerformance perf = getCachedPerformance(empId);
        VendingMachine machine = vendingMachineService.selectVendingMachineByInnerCode(innerCode);

        double fitness = 0.0;

        // 1. 工作效率适应度 (25%)
        fitness += calculateEfficiencyFitness(perf) * 0.25;

        // 2. 技能匹配适应度 (20%)
        fitness += performanceCalculator.calculateSkillMatch(empId, machine) * 20;

        // 3. 负载均衡适应度 (20%)
        fitness += calculateLoadFitness(perf.getCurrentWorkload()) * 0.20;

        // 4. 距离适应度 (15%)
        double distance = distanceCalculator.calculateDistanceLevel(
                distanceCalculator.calculateDistance(getEmpById(empId), machine));
        fitness += (1 - distance) * 15; // 距离越近适应度越高

        // 5. 历史表现适应度 (10%)
        fitness += calculateHistoricalFitness(empId, taskType) * 0.10;

        // 6. 紧急程度适应度 (10%)
        fitness += calculateUrgencyFitness(innerCode) * 0.10;

        return Math.min(fitness, 10.0);
    }

    private Emp getEmpById(Long empId) {
        // 简化实现，实际应该从数据库查询
        Emp emp = new Emp();
        emp.setId(empId);
        return emp;
    }

    private double calculateEfficiencyFitness(EmployeePerformance perf) {
        if (perf.getAvgCompletionTime() <= 2.0) return 10.0;
        if (perf.getAvgCompletionTime() <= 3.0) return 8.0;
        if (perf.getAvgCompletionTime() <= 4.0) return 6.0;
        if (perf.getAvgCompletionTime() <= 5.0) return 4.0;
        return 2.0;
    }

    private double calculateLoadFitness(Integer workload) {
        if (workload == 0) return 10.0;
        if (workload <= 2) return 8.0;
        if (workload <= 4) return 6.0;
        if (workload <= 6) return 4.0;
        return 2.0;
    }

    private double calculateHistoricalFitness(Long empId, String taskType) {
        EmployeeAllocationHistory history = allocationHistory.get(empId);
        if (history == null) return 5.0;

        Double successRate = history.getTaskTypeSuccessRate().get(taskType);
        return successRate != null ? successRate * 10 : 5.0;
    }

    private double calculateUrgencyFitness(String innerCode) {
        // 根据设备状态判断紧急程度
        VendingMachine machine = vendingMachineService.selectVendingMachineByInnerCode(innerCode);
        if (machine.getAutoCreateCount() >= 3) {
            return 10.0; // 紧急
        }
        return 5.0; // 普通
    }

    /**
     * 创建特征向量（用于神经网络）
     */
    private double[] createFeatureVector(Emp emp, String innerCode, String taskType) {
        EmployeePerformance perf = getCachedPerformance(emp.getId());
        VendingMachine machine = vendingMachineService.selectVendingMachineByInnerCode(innerCode);

        return new double[]{
                perf.getCompletedTasks() / 100.0,                    // 归一化经验
                Math.min(perf.getCurrentWorkload() / 10.0, 1.0),     // 归一化负载
                perf.getSuccessRate(),                               // 成功率
                perf.getAvgCompletionTime() / 8.0,                   // 归一化效率
                performanceCalculator.calculateSkillMatch(emp.getId(), machine), // 技能匹配度
                distanceCalculator.calculateDistanceLevel(
                        distanceCalculator.calculateDistance(emp, machine)), // 距离等级
                getTimeOfDayFactor(),                                // 时间因子
                getDayOfWeekFactor()                                 // 星期因子
        };
    }

    private double getTimeOfDayFactor() {
        Calendar cal = Calendar.getInstance();
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        if (hour >= 9 && hour <= 17) return 0.8;  // 工作时间
        if (hour >= 7 && hour <= 21) return 0.6;  // 扩展时间
        return 0.3; // 非工作时间
    }

    private double getDayOfWeekFactor() {
        Calendar cal = Calendar.getInstance();
        int day = cal.get(Calendar.DAY_OF_WEEK);
        return (day == Calendar.SATURDAY || day == Calendar.SUNDAY) ? 0.6 : 0.9;
    }

    /**
     * 自适应分数融合
     */
    private Map<Long, Double> adaptiveScoreFusion(Map<Long, AlgorithmScores> algorithmScores, String taskType) {
        Map<Long, Double> finalScores = new HashMap<>();
        AlgorithmWeights weights = new AlgorithmWeights().calculateDynamicWeights(taskType);

        for (Map.Entry<Long, AlgorithmScores> entry : algorithmScores.entrySet()) {
            double fusedScore = entry.getValue().getWeightedScore(weights);

            // 添加多样性保护
            double protectedScore = 2.0 + (fusedScore * 0.8); // 确保最低2分，压缩范围

            finalScores.put(entry.getKey(), protectedScore);
        }

        log.debug("自适应分数融合完成，最终评分数量: {}", finalScores.size());
        return finalScores;
    }

    /**
     * 执行选择策略
     */
    private Long executeSelectionStrategy(Map<Long, Double> finalScores, List<Emp> candidates) {
        List<Long> candidateIds = candidates.stream().map(Emp::getId).collect(Collectors.toList());

        double strategyChoice = Math.random();

        if (strategyChoice < 0.4) {
            // 40%概率使用模拟退火
            SimulatedAnnealingSelector sa = new SimulatedAnnealingSelector();
            return sa.select(finalScores, candidateIds);
        } else if (strategyChoice < 0.7) {
            // 30%概率使用禁忌搜索
            TabuSearchSelector ts = new TabuSearchSelector();
            return ts.select(finalScores, candidateIds);
        } else {
            // 30%概率使用Q学习
            QLearningSelector ql = new QLearningSelector();
            return ql.select(finalScores, candidateIds);
        }
    }

    /**
     * 记录分配历史
     */
    private void recordAllocationHistory(Long empId, String innerCode, String taskType, Map<Long, Double> scores) {
        EmployeeAllocationHistory history = allocationHistory.computeIfAbsent(empId, k -> new EmployeeAllocationHistory());
        history.setEmpId(empId);
        history.recordAssignment(taskType, true, 1.0); // 简化记录

        // 记录算法性能
        performanceMonitor.recordAlgorithmPerformance("Genetic",
                scores.getOrDefault(empId, 5.0), true);
        performanceMonitor.recordAlgorithmPerformance("PSO",
                scores.getOrDefault(empId, 5.0), true);
        // 记录其他算法...
    }

    /**
     * 获取缓存的员工绩效
     */
    private EmployeePerformance getCachedPerformance(Long empId) {
        long currentTime = System.currentTimeMillis();
        Long expiryTime = cacheExpiry.get(empId);

        if (expiryTime != null && currentTime < expiryTime) {
            return performanceCache.get(empId);
        }

        // 缓存过期，重新计算
        EmployeePerformance performance = performanceCalculator.calculateEmployeePerformance(empId);
        performanceCache.put(empId, performance);
        cacheExpiry.put(empId, currentTime + CACHE_DURATION);

        return performance;
    }

    /**
     * 回退随机选择
     */
    private Long fallbackRandomSelection(List<Emp> candidates) {
        Emp emp = candidates.get((int) (Math.random() * candidates.size()));
        log.warn("使用随机选择员工: {}", emp.getId());
        return emp.getId();
    }

    /**
     * 自适应回退策略
     */
    private Long adaptiveFallback(List<Emp> candidates, String taskType) {
        // 基于简单规则的回退
        return candidates.stream()
                .min(Comparator.comparingInt(emp -> getCachedPerformance(emp.getId()).getCurrentWorkload()))
                .map(Emp::getId)
                .orElseGet(() -> fallbackRandomSelection(candidates));
    }

    /**
     * 清理缓存
     */
    public void clearCache() {
        performanceCache.clear();
        cacheExpiry.clear();
        log.info("员工分配器缓存已清理");
    }

    /**
     * 获取性能统计
     */
    public Map<String, Object> getPerformanceStats() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("cacheSize", performanceCache.size());
        stats.put("allocationHistorySize", allocationHistory.size());
        stats.put("algorithmPerformance", performanceMonitor.getAlgorithmExecutionCount());
        return stats;
    }
}